package org.ghost.spring.cloud.hystrix.demo.component.handler;

import org.apache.commons.lang3.StringUtils;
import org.ghost.spring.cloud.hystrix.demo.common.component.RequestContext;
import org.ghost.spring.cloud.hystrix.demo.common.constant.SystemErrorCodeEnum;
import org.ghost.spring.cloud.hystrix.demo.dto.RspDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Locale;

@ControllerAdvice
public class GlobalExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @Autowired
    protected MessageSource messageSource;


    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public RspDTO privateExceptionHandler(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder errorMessage = new StringBuilder("参数错误:");
        int index = 0;
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorMessage.append(index).append(": ").append(fieldError.getDefaultMessage()).append(";");
            index++;
        }

        RspDTO rspDTO = new RspDTO(SystemErrorCodeEnum.SYSTEM_ERROR.getCode(), errorMessage.substring(0, errorMessage.length() - 1));

        RequestContext.remove();

        return rspDTO;
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
    public RspDTO privateExceptionHandler(BindException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder errorMessage = new StringBuilder("参数错误:");
        int index = 0;
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errorMessage.append(fieldError.getField()).append(": ").append(fieldError.getDefaultMessage()).append(";");
            index++;
        }

        RspDTO rspDTO = new RspDTO(SystemErrorCodeEnum.SYSTEM_ERROR.getCode(), errorMessage.substring(0, errorMessage.length() - 1));

        RequestContext.remove();

        return rspDTO;
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public RspDTO privateExceptionHandler(HttpMessageNotReadableException ex) {
        return this.parserCodeMessage(SystemErrorCodeEnum.PARAM_ERROR.getCode(), "参数格式错误");
    }

    @ExceptionHandler(Throwable.class)
    @ResponseBody
    public RspDTO privateExceptionHandler(Throwable ex) {
        if (logger.isErrorEnabled()) {
            logger.error("系统错误: {}, {}", ex.getMessage(), ex);
        }
        return this.parserCodeMessage(SystemErrorCodeEnum.SYSTEM_ERROR.getCode(), SystemErrorCodeEnum.SYSTEM_ERROR.getMessage());
    }

    private RspDTO parserCodeMessage(String code, String msg) {
        RspDTO rspDTO;
        if (StringUtils.isNotBlank(code)) {
            Locale locale = RequestContext.getContext().getLocale();
            String message = "";
            try {
                message = messageSource.getMessage(code, null, locale);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (StringUtils.isBlank(message)) {
                message = msg;
            }

            rspDTO = new RspDTO(code, message);
        } else {
            rspDTO = new RspDTO(SystemErrorCodeEnum.SYSTEM_ERROR.getCode(), msg);
        }

        RequestContext.remove();

        return rspDTO;
    }
}
